package com.shinbada.modules.sys.web;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.shinbada.common.json.AjaxJson;
import com.shinbada.common.utils.CacheUtils;
import com.shinbada.common.utils.FileUtils;
import com.shinbada.common.utils.StringUtils;
import com.shinbada.config.properties.FileProperties;
import com.shinbada.config.properties.ShinProperites;
import com.shinbada.core.persistence.Page;
import com.shinbada.core.security.shiro.JWTUtil;
import com.shinbada.core.security.shiro.PermissionsUtil;
import com.shinbada.core.web.BaseController;
import com.shinbada.excel.ExcelKit;
import com.shinbada.excel.modle.ImportExcelResult;
import com.shinbada.excel.modle.UploadModle;
import com.shinbada.exception.ServiceException;
import com.shinbada.modules.sys.entity.*;
import com.shinbada.modules.sys.service.RoleService;
import com.shinbada.modules.sys.service.UserService;
import com.shinbada.modules.sys.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 用户Controller
 *
 * @author initcap
 * @version 2016-8-29
 */
@RestController
@RequestMapping("/sys/user")
@Api(tags = "用户管理")
public class UserController extends BaseController {

    @Autowired
    private UserService userService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private FileProperties fileProperties;

    @ModelAttribute
    public User get(@RequestParam(required = false) String id) {
        if (StringUtils.isNotBlank(id)) {
            return userService.get(id);
        } else {
            return new User();
        }
    }

    @GetMapping("queryById")
    @ApiOperation(value = "查询用户")
    public AjaxJson queryById(User user) {
        return AjaxJson.success().put("user", user);
    }

    @RequiresPermissions("user")
    @GetMapping("list")
    @ApiOperation("获取所有用户信息")
    public AjaxJson list(User user, HttpServletRequest request, HttpServletResponse response) {
        Page<User> page = userService.findPage(new Page<>(request, response), user);
        return AjaxJson.success().put("page", page);
    }

    @RequiresPermissions("sys:user:changelogin")
    @PostMapping("changelogin")
    @ApiOperation("超级管理员切换登录用户接口")
    public AjaxJson adminLogin(@RequestParam("userName") String userName) {
        AjaxJson j = new AjaxJson();
        User user = UserUtils.getByLoginName(userName);
        if (user != null) {
            if (ShinProperites.NO.equals(user.getLoginFlag())) {
                j.setSuccess(false);
                j.setMsg("该用户已经被禁止登陆!");
            } else {
                String token = UserUtils.getToken();
                if (org.apache.commons.lang3.StringUtils.isNotBlank(token)) {
                    CacheUtils.remove(UserUtils.getUser().getLoginName());
                    UserUtils.clearCache();
                    UserUtils.getSubject().logout();
                }
                j.setSuccess(true);
                j.put(JWTUtil.TOKEN, JWTUtil.createAccessToken(userName, user.getPassword()));
                j.put(JWTUtil.REFRESH_TOKEN, JWTUtil.createRefreshToken(userName, user.getPassword()));
            }
        }
        return j;
    }

    @RequiresPermissions("user")
    @PostMapping("save")
    @ApiOperation(value = "保存用户")
    public AjaxJson save(User user) {
        if (shinProperites.isDemoMode()) {
            return AjaxJson.error("演示模式，不允许操作!");
        }
        if (UserUtils.SYSTEM_USER_LOGIN_NAME.equals(user.getLoginName()) || UserUtils.ADMINISTRATOR_USER_LOGIN_NAME.equals(user.getLoginName())) {
            return AjaxJson.error("系统保留登录名,不能准使用!");
        }
        // 如果新密码为空，则不更换密码
        if (StringUtils.isNotBlank(user.getNewPassword())) {
            user.setPassword(UserService.entryptPassword(user.getNewPassword()));
        }
        /**
         * 后台hibernate-validation插件校验
         */
        String errMsg = beanValidator(user);
        if (StringUtils.isNotBlank(errMsg)) {
            return AjaxJson.error(errMsg);
        }
        // 角色数据有效性验证，过滤不在授权内的角色
        List<Role> roleList = Lists.newArrayList();
        List<String> roleIdList = user.getRoleIdList();
        for (String roleId : roleIdList) {
            roleList.add(roleService.get(roleId));
        }
        user.setRoleList(roleList);

        // 保存用户信息
        userService.saveUser(user);
        // 清除当前用户缓存
        if (user.getLoginName().equals(UserUtils.getUser().getLoginName())) {
            UserUtils.clearCache();
        }
        return AjaxJson.success("保存用户'" + user.getLoginName() + "'成功!");
    }

    @ApiOperation(value = "删除用户")
    @RequiresPermissions("sys:user:del")
    @DeleteMapping("delete")
    public AjaxJson delete(String ids) {
        String[] idArray = ids.split(",");
        if (shinProperites.isDemoMode()) {
            return AjaxJson.error("演示模式，不允许操作!");
        }
        StringBuffer msg = new StringBuffer();
        boolean success = true;
        for (String id : idArray) {
            User user = userService.get(id);
            if (UserUtils.getUser().getId().equals(user.getId())) {
                success = false;
                msg.append("[" + user.getLoginName() + "]删除失败，不允许删除当前用户!<br/>");
            } else if (User.isAdmin(user.getId())) {
                success = false;
                //删除用户失败, 不允许删除超级管理员用户
                msg.append("[" + user.getLoginName() + "]删除失败，不允许删除超级管理员!<br/>");
            } else {
                msg.append("[" + user.getLoginName() + "]删除成功!<br/>");
                //删除用户成功
                userService.deleteUser(user);
            }
        }
        if (success) {
            return AjaxJson.success(msg.toString());
        } else {
            return AjaxJson.error(msg.toString());
        }
    }

    @RequiresPermissions("user")
    @PostMapping("saveInfo")
    @ApiOperation(value = "修改个人资料")
    public AjaxJson infoEdit(User user) {
        User currentUser = UserUtils.getUser();
        logger.debug("获取旧的用户登录信息: {}, 传入信息: {}, 旧的登录名: {}", currentUser.getLoginName(), user.getLoginName(), user.getOldLoginName());
        if (shinProperites.isDemoMode()) {
            return AjaxJson.error("演示模式，不允许操作！");
        }
        if (user.getName() != null) {
            currentUser.setName(user.getName());
        }
        if (user.getEmail() != null) {
            currentUser.setEmail(user.getEmail());
        }
        if (user.getMobile() != null) {
            currentUser.setMobile(user.getMobile());
        }
        if (user.getRemarks() != null) {
            currentUser.setRemarks(user.getRemarks());
        }
        if (user.getSign() != null) {
            currentUser.setSign(user.getSign());
        }
        if (user.getLoginName() != null && !currentUser.getLoginName().equals(user.getLoginName())) {
            if (StringUtils.isBlank(user.getOldLoginName())) {
                throw new ServiceException("想修改登录名必须提供旧的登录名称!");
            }
            userService.checkLoginNameExist(null, user.getLoginName());
            currentUser.setOldLoginName(user.getOldLoginName());
            currentUser.setLoginName(user.getLoginName());
        }
        userService.updateUserInfo(currentUser);
        return AjaxJson.success("修改个人资料成功!")
                .put(JWTUtil.TOKEN, JWTUtil.createAccessToken(user.getLoginName(), user.getPassword()))
                .put(JWTUtil.REFRESH_TOKEN, JWTUtil.createRefreshToken(user.getLoginName(), user.getPassword()));
    }

    @RequiresPermissions("user")
    @PostMapping("imageUpload")
    @ApiOperation(value = "上传头像")
    public AjaxJson imageUpload(MultipartFile file) throws IllegalStateException, IOException {
        User currentUser = UserUtils.getUser();
        // 判断文件是否为空
        if (!file.isEmpty()) {
            if (fileProperties.isImage(file.getOriginalFilename())) {
                // 文件保存路径
                String realPath = FileKit.getAttachmentDir() + "sys/user/images/";
                // 转存文件
                FileUtils.createDirectory(realPath);
                file.transferTo(new File(realPath + file.getOriginalFilename()));
                currentUser.setPhoto(FileKit.getAttachmentUrl() + "sys/user/images/" + file.getOriginalFilename());
                userService.updateUserInfo(currentUser);
                return AjaxJson.success("上传成功!").put("path", FileKit.getAttachmentUrl() + "sys/user/images/" + file.getOriginalFilename());
            } else {
                return AjaxJson.error("请上传图片!");
            }

        } else {
            return AjaxJson.error("文件不存在!");
        }
    }

    @RequiresPermissions("user")
    @GetMapping("info")
    @ApiOperation(value = "获取当前用户信息")
    public AjaxJson infoData() {
        return AjaxJson.success("获取个人信息成功!").put("role", UserUtils.getRoleList()).put("user", UserUtils.getUser());
    }


    @RequiresPermissions("user")
    @PostMapping("savePwd")
    @ApiOperation(value = "修改密码")
    public AjaxJson savePwd(String oldPassword, String newPassword) {
        User user = UserUtils.getUser();
        if (StringUtils.isNotBlank(oldPassword) && StringUtils.isNotBlank(newPassword)) {
            if (shinProperites.isDemoMode()) {
                return AjaxJson.error("演示模式，不允许操作！");
            }
            if (UserService.validatePassword(oldPassword, user.getPassword())) {
                userService.updatePasswordById(user.getId(), user.getLoginName(), newPassword);
                return AjaxJson.success("修改密码成功！");
            } else {
                return AjaxJson.error("修改密码失败，旧密码错误！");
            }
        }
        return AjaxJson.error("参数错误！");
    }

    @RequiresPermissions("sys:user:reset")
    @PostMapping("resetPwd")
    @ApiOperation(value = "管理员重置密码")
    public AjaxJson resetPwd(String userId, String loginName, String newPassword) {
        if (StringUtils.isNotBlank(userId) && StringUtils.isNotBlank(newPassword) && StringUtils.isNotBlank(loginName)) {
            if (shinProperites.isDemoMode()) {
                return AjaxJson.error("演示模式，不允许操作！");
            }
            userService.updatePasswordById(userId, loginName, newPassword);
            return AjaxJson.success("修改密码成功！");
        }
        return AjaxJson.error("参数错误！");
    }

    @RequiresPermissions("user")
    @PostMapping("/domains")
    @ApiOperation(value = "赋权管理域")
    public AjaxJson domains(String userId, String domains) {
        if (StringUtils.isNotBlank(userId) && StringUtils.isNotBlank(domains)) {
            if (shinProperites.isDemoMode()) {
                return AjaxJson.error("演示模式，不允许操作！");
            }
            userService.updateUserDomains(userId, domains);
        }
        return AjaxJson.success();
    }

    @PostMapping("saveSign")
    @ApiOperation(value = "用户签名")
    public AjaxJson saveSign(User user) {
        User currentUser = UserUtils.getUser();
        currentUser.setSign(user.getSign());
        userService.updateUserInfo(currentUser);
        return AjaxJson.success("设置签名成功!");
    }

    @RequiresPermissions("user")
    @GetMapping("treeData")
    public List<Map<String, Object>> treeData(@RequestParam(required = false) String officeId, HttpServletResponse response) {
        List<Map<String, Object>> mapList = Lists.newArrayList();
        List<User> list = userService.findUserByOfficeId(officeId);
        for (int i = 0; i < list.size(); i++) {
            User e = list.get(i);
            Map<String, Object> map = Maps.newHashMap();
            map.put("id", "u_" + e.getId());
            map.put("pId", officeId);
            map.put("name", StringUtils.replace(e.getName(), " ", ""));
            mapList.add(map);
        }
        return mapList;
    }

    @ApiOperation("web端ajax验证手机号是否可以注册（数据库中不存在）")
    @GetMapping("validateMobile")
    public AjaxJson validateMobile(String mobile) {
        User user = userService.findUniqueByProperty("mobile", mobile);
        if (user == null) {
            return AjaxJson.success().put("noExist", true);
        } else {
            return AjaxJson.success().put("noExist", false);
        }
    }


    @ApiOperation(value = "用户权限")
    @RequiresPermissions("user")
    @GetMapping("getPermissions")
    public Set<String> getPermissions() {
        return PermissionsUtil.currentUserPermissions();
    }


    @GetMapping("getMenus")
    @RequiresPermissions("user")
    public AjaxJson getMenus() {
        AjaxJson j = new AjaxJson();
        j.put("dictList", this.getDicts());
        j.put("permissions", PermissionsUtil.currentUserPermissions());
        j.put("menuList", MenuUtils.getMenus());
        j.put("routerList", RouterUtils.getRoutersByMenu());
        return j;
    }

    private Map<String, List<DictValue>> getDicts() {
        return DictUtils.getDictMap();
    }

    @RequiresPermissions("sys:user:export")
    @GetMapping(value = "/export")
    @ApiOperation("导出用户数据")
    public void exportModel(User user, HttpServletResponse response) {
        ExcelKit.$Export(User.class, response).downXlsx(userService.findAllList(user), false);
    }

    @RequiresPermissions("sys:user:import")
    @GetMapping(value = "/template")
    @ApiOperation("用户导入模版")
    public void template(HttpServletResponse response) {
        ExcelKit.$Export(UserImport.class, response).downXlsx(new ArrayList<>(), true);
    }

    @RequiresPermissions("sys:user:import")
    @PostMapping(value = "/uploadExcel")
    @ApiImplicitParam(name = "modle", paramType = "query", allowableValues = "skip,exit,cover")
    @ApiOperation("导入文件,下载模版为/template")
    public AjaxJson importExcel(MultipartFile file, UploadModle modle) {
        if (shinProperites.isDemoMode()) {
            return AjaxJson.error("演示模式，不允许操作！");
        }
        ImportExcelResult<UserImport> result = userService.uploadExcel(file, modle);
        return AjaxJson.success().put("result", result);
    }

    @GetMapping(value = "/listByOfficeAndPostAndUser")
    @ApiOperation("根据部门-岗位-用户获取用户集合信息:分别主要传值：office 部门、post 岗位、user 用户")
    public AjaxJson listByOfficeAndPostAndUser(String office, String post, String user) {
        return AjaxJson.success(userService.listByOfficeAndPostAndUser(new Office(office), new Post(post), new User(user)));
    }

}
